package com.study.kt._04project.game_tank.model

import com.study.kt._04project.game_tank.Config
import com.study.kt._04project.game_tank.business.*
import com.study.kt._04project.game_tank.enums.Direction
import org.itheima.kotlin.game.core.Composer
import org.itheima.kotlin.game.core.Painter
import java.util.*


/**
 * 敌方坦克
 * 有可移动的能力（避开阻挡物）-->如果碰撞到障碍物则不能移动
 * 有自动移动的能力
 *
 * 地方坦克相互碰撞也应该改变移动方向，所以地方坦克应该具备障碍物的能力
 *         实现Blockable接口之后返现坦克原地打转，因为地方坦克自己也为障碍物出现时自己和自己重叠发生碰撞，要改变方向
 *         所以在产生错误方向的通知时要排除自己
 *
 *  地方坦克具有自动射击的能力
 */
class Enemy(override var x: Int, override var y: Int) : Moveable, AutoMoveable,
    Blockable, AutoShoot, Sufferable, Destoryable {
    override var blood: Int = 3

    override var currentDirection: Direction = Direction.DOWN
    override val speed: Int = 8
    override val width: Int = Config.block
    override val height: Int = Config.block

    //记录被阻挡物阻挡，不可以移动的方向
    var badDirection: Direction? = null

    //控制自动射击的频率不能太快
    //上一次射击时间
    var lastShootTime = 0L
    //频率控制在800ms一次
    var shootFrequency = 800

    //防止移动过快，则设置移动频率
    var lastMoveTime = 0L
    val moveFrequency = 50

    override fun draw() {
        val img = when (currentDirection) {
            Direction.UP -> "img/enemy_1_u.gif"
            Direction.DOWN -> "img/enemy_1_d.gif"
            Direction.LEFT -> "img/enemy_1_l.gif"
            Direction.RIGHT -> "img/enemy_1_r.gif"
        }
        Painter.drawImage(img, x, y)
    }

    //遇到错误方向
    override fun notifyCollisition(blockable: Blockable?, direction: Direction?) {
        badDirection = direction
    }

    //移动与我方坦克类似，不过我方坦克是用户输入
    override fun autoMove() {

        //遇到障碍物则不能继续移动，而且要改变移动方向
        if (currentDirection == badDirection) {
            currentDirection = makeRandomDirection(badDirection)
            return
        }

        //判断有没有到可以移动的时间
        val current = System.currentTimeMillis()
        if (current - lastMoveTime < moveFrequency) return
        lastMoveTime = current

        //根据当前方向与速度改变坐标
        when (currentDirection) {
            //移动的距离为速
            Direction.UP -> y -= speed
            Direction.DOWN -> y += speed
            Direction.LEFT -> x -= speed
            Direction.RIGHT -> x += speed
        }

        //边界检测
        if (x < 0) x = 0
        if (y < 0) y = 0
        if (x > Config.gameWidth - Config.block) x = Config.gameWidth - Config.block
        if (y > Config.gameHeight - Config.block) y = Config.gameHeight - Config.block
    }

    //遇到障碍物，产生一个随机方向，继续移动
    private tailrec fun makeRandomDirection(badDirection: Direction?): Direction {
        val newDirection = when (Random().nextInt(4)) {
            0 -> Direction.UP
            1 -> Direction.DOWN
            2 -> Direction.LEFT
            3 -> Direction.RIGHT
            else -> Direction.UP
        }

        //如果移动的方向时错误的方向还要继续改变方向
        if (newDirection == badDirection) {
            //使用递归知道找出一个正确的方向
            //tailrec关键字将递归改为尾递归，kotlin做优化，比Java递归性能强大
            return makeRandomDirection(badDirection)
        }

        return newDirection
    }

    override fun autoShoot(): View? {

        //判断没有超过射击间隔，则不射击
        val current = System.currentTimeMillis()

        //没有到达可以射击时间，则不射击
        if ((current - lastShootTime) < shootFrequency) return null
        lastShootTime = current

        //谁发射出的子弹，所有者就是谁
        return Bullet(this, currentDirection) { bulletWidth, bulletHeight ->
            //坦克位置信息
            val tankX: Int = x
            val tankY: Int = y
            val tankWidth: Int = width
            val tankHeight: Int = height

            //子弹位置信息
            var bulletX = 0
            var bulletY = 0

            //计算字段的坐标，子弹要从坦克的中间发射出来，还有考虑位置因素
            when (currentDirection) {
                Direction.UP -> {
                    //子弹的x值=坦克x坐标+(坦克宽度-子弹宽度)/2
                    //子弹的y值=坦克y坐标-子弹的高度/2
                    //子弹的宽高信息由子弹计算完毕传给外界
                    bulletX = tankX + (tankWidth - bulletWidth) / 2
                    bulletY = tankY - bulletHeight / 2
                }
                Direction.DOWN -> {
                    bulletX = tankX + (tankWidth - bulletWidth) / 2
                    bulletY = tankY + tankHeight - bulletHeight / 2
                }
                Direction.LEFT -> {
                    bulletX = tankX - bulletWidth / 2
                    bulletY = tankY + (tankHeight - bulletHeight) / 2
                }
                Direction.RIGHT -> {
                    bulletX = tankX + (tankWidth - bulletWidth / 2)
                    bulletY = tankY + (tankHeight - bulletHeight) / 2
                }
            }
            Pair(bulletX, bulletY)
        }
    }

    override fun notifySuffer(attachable: Attachable): Array<View>? {
        //敌方坦克不能互相攻击
        if (attachable.owner is Enemy) {
            return null
        }
        blood -= attachable.attachPower
        Composer.play("snd/hit.wav")
        return arrayOf(Blast(x, y))
    }

    override fun isDestory(): Boolean = blood <= 0

}